/*
 * 版权所有 ( c ) 联想集团有限公司 2005-2009 保留所有权利。
 * 项目：	Lenovo Push Service
 * 文件名：	HibernateSessionManager.java
 * 版本:    1.0
 * 描述：	Defines class for Hibernate session management
 * 作者：	刘兵召
 * 日期：	2009-7-10
 * 修改历史：
 * 【时间】		【修改者】	【修改内容】
 */
package com.feng.demo.hibernate.jta.orm.hibernate;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import com.feng.demo.hibernate.jta.orm.dao.DaoException;
import com.lenovo.lps.log.Log;


/**
 * Class used for session management.
 *
 */
@SuppressWarnings("unchecked")
public class HibernateSessionManager {

   private static final SessionFactory sessionFactory;

   private static final ThreadLocal threadSession = new ThreadLocal();

   private static final ThreadLocal threadTransaction = new ThreadLocal();
   private static final Log log = Log.getInstance(HibernateSessionManager.class);
   //private static DataSource dataSource = (DataSource)IocUtils.getBean("springAppStoreDataSource");
   //private static Log log = LogFactory.getLog(HibernateSessionManager.class);

   static {
      try {
         sessionFactory = new Configuration().configure("hibernate_1.cfg.xml").buildSessionFactory();
      } catch (Throwable ex) {
         log.error("Initial SessionFactory creation failed.", ex);
         throw new DaoException("Initial SessionFactory creation failed.", ex);
      }
   }

   /**
    * Private empty constructor. Cannot be used to create instance. Call static
    * methods directly.
    *  
    */
   private HibernateSessionManager() {

   }

   /**
    * Get session associated with current thread. Create new one from session
    * factory if no session found and openSession is true.
    * 
    * @param openSession whether to open new session if no one found
    * @return session
    * @throws DaoException
    */
   public static Session getSession(boolean openSession) throws DaoException {
      Session s = (Session) threadSession.get();
      if (openSession) {
         try {
            if (s == null) {
               s = sessionFactory.openSession();
               //读取Spring DataSource
            	//s = sessionFactory.openSession(dataSource.getConnection());
               threadSession.set(s);
            }
         } catch (HibernateException ex) {
            log.error("Fail to open session", ex);
            throw new DaoException("Fail to open session", ex);
         } /*catch (SQLException ex) {
        	 log.error("SQLException:", ex);
        	 throw new DaoException("SQLException:", ex);
		}*/
      }
      return s;
   }

   /**
    * Set new session associated with current thread. Return old session
    * if any.
    * 
    * @param session new session
    * @return session replaced
    */
   public static Session setSession(Session session) {
      Session s = (Session) threadSession.get();
      threadSession.set(session);
      return s;
   }

   /**
    * Close session associated with current thread if exists.
    * 
    * @throws DaoException
    */
   public static void closeSession() throws DaoException {
      try {
         Session s = (Session) threadSession.get();
         threadSession.set(null);
         if (s != null && s.isOpen())
            s.close();
      } catch (HibernateException ex) {
         log.error("Fail to close session", ex);
         throw new DaoException("Fail to open session", ex);
      }
   }

   /**
    * Begin transaction associated with current thread. Begin new one from
    * session associated with current thread if no transaction found.
    * 
    * @throws DaoException
    */
   public static void beginTransaction() throws DaoException {
      Transaction tx = (Transaction) threadTransaction.get();
      try {
         if (tx == null) {
            tx = getSession(true).beginTransaction();
            threadTransaction.set(tx);
         }
      } catch (HibernateException ex) {
         log.error("Fail to begin transaction", ex);
         throw new DaoException("Fail to begin transaction", ex);
      }
   }

   /**
    * Commit transaction associated with current thread.
    * 
    * @throws DaoException
    */
   public static void commitTransaction() throws DaoException {
      Transaction tx = (Transaction) threadTransaction.get();
      try {
         if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack())
            tx.commit();
         threadTransaction.set(null);
      } catch (HibernateException ex) {
         rollbackTransaction();
         log.error("Fail to commit transaction", ex);
         throw new DaoException("Fail to commit transaction", ex);
      }
   }

   /**
    * Rollback transaction associated with current thread. Close session in the end.
    * 
    * @throws DaoException
    */
   public static void rollbackTransaction() throws DaoException {
      Transaction tx = (Transaction) threadTransaction.get();
      try {
         threadTransaction.set(null);
         if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {
            tx.rollback();
         }
      } catch (HibernateException ex) {
         log.error("Fail to rollback transaction", ex);
         throw new DaoException("Fail to rollback transaction", ex);
      } finally {
         closeSession();
      }
   }

   /**
    * Get static session factory.
    * 
    * @return session factory
    */
   public static SessionFactory getSessionFactory() {
      return sessionFactory;
   }
}